package com.tabnet.form.client;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.tabnet.beans.commande.Commande;
import com.tabnet.beans.commande.LigneCommande;
import com.tabnet.beans.personnes.Client;
import com.tabnet.beans.produit.Accessoire;
import com.tabnet.beans.produit.Option;
import com.tabnet.beans.produit.Produit;
import com.tabnet.beans.produit.ProduitCMD;
import com.tabnet.dao.DAOAccessoire;
import com.tabnet.dao.DAOCommande;
import com.tabnet.dao.DAOException;
import com.tabnet.dao.DAOLigneCommande;
import com.tabnet.form.FormValidationException;

public class AjoutPanierForm {

    public static final String PARAM_QUANTITE		= "qteProduit";
    public static final String PARAM_COULEUR		= "OPT_C";
    public static final String PARAM_CAPACITE		= "OPT_D";
    public static final String PARAM_WIFI			= "OPT_W";
    
    private String resultat;
    private Map<String, String> erreurs = new HashMap<String, String>();
    private DAOCommande _oDAOCommande;
    private DAOAccessoire _oDAOAccessoire;
    private DAOLigneCommande _oDAOLigneCommande;

    public AjoutPanierForm( DAOCommande pDAOCommande, DAOAccessoire pDAOAccessoire, DAOLigneCommande pDAOLigneCommande) {
        this._oDAOCommande = pDAOCommande;
        this._oDAOAccessoire = pDAOAccessoire;
        this._oDAOLigneCommande = pDAOLigneCommande;
    }

    public Map<String, String> getErreurs() {
        return this.erreurs;
    }
    public String getResultat() {
        return this.resultat;
    }

    private void setErreur( String champ, String message ) {
        this.erreurs.put( champ, message );
    }

    /**
     * <p>Fonction static getValeurParametre<br />
     * Utilitaire qui retourne null si un paramètre est vide, et son
     * contenu sinon.</p>
     * @param request : objet HttpServletRequest
     * @param nomChamp : nom du champ
     * @return la valeur du champ
     */
    private static String getValeurParametre( HttpServletRequest request, String nomChamp ) {
        String valeur = request.getParameter( nomChamp );
        if ( valeur == null || valeur.trim().length() == 0 ) {
            return null;
        } else {
            return valeur;
        }
    }
    
    /**
     * <p>Fonction getValeurParametre<br />
     * Utilitaire qui retourne null si un paramètre est vide, et son
     * contenu sinon.</p>
     * @param request : objet HttpServletRequest
     * @param nomChamp : nom du champ
     * @return la valeur du champ
     */
    private boolean getValeurParametreBoolean( HttpServletRequest request, String nomChamp ) {
        String valeur = request.getParameter( nomChamp );
        if ( valeur == null || valeur.trim().length() == 0) 
            return false;
        
        if (valeur.equals("on"))
            return true;
        
        return false;
    }
    
    /**
     * <p>Fonction ajoutPanier<br />
     * Ajoute un produit avec options et accessoires dans la commande "En cours".</p>
     * @param request : objet HttpServletRequest
     * @param pClient : le client connecter
     * @param pProduit : Male produit selectionner
     */
    public void ajoutPanier(HttpServletRequest request, Client pClient, Produit pProduit) {
    	
    	Commande oCommande = null;
    	LigneCommande oLigneCommande = new LigneCommande();
    	ProduitCMD oProduitCMD = new ProduitCMD();
    	
    	//Récupération de la commande en cours du client
    	try {
			oCommande = this._oDAOCommande.getCommandeEnCours(pClient.getId());
		}
    	catch (DAOException e) {
        	this.setErreur( "imprévu", "Erreur imprévue lors de la récupération du panier dans la base de données." );
            this.resultat = "Échec de l'ajout du produit au panier.";
		}
    	
    	//Création d'une nouvelle commande
    	if (oCommande == null){
    		oCommande = new Commande();
    		try {
				oCommande.setNum(this._oDAOCommande.addCommande(pClient));
			}
    		catch (DAOException e) {
            	this.setErreur( "imprévu", "Erreur imprévue lors de la création du panier dans la base de données." );
                this.resultat = "Échec de l'ajout du produit au panier.";
			}
    		oCommande.setClient(pClient);
    	}
    	
    	int qteProduit = Integer.parseInt(getValeurParametre(request, PARAM_QUANTITE));
    	//options
        String color = getValeurParametre(request, PARAM_COULEUR);
        String capacity = getValeurParametre(request, PARAM_CAPACITE);
        boolean wireless = getValeurParametreBoolean(request, PARAM_WIFI);
    	        
        // les tests de validation des données
        this.traiterQuantite(qteProduit, oLigneCommande);
        
        //Traitement des options
        Map<String, Option> mapOption = new HashMap<String, Option>();
        this.traiterCouleur(color, pProduit.getLstOptionP().get(PARAM_COULEUR), mapOption);
        this.traiterCapaciter(capacity, pProduit.getLstOptionP().get(PARAM_CAPACITE), mapOption);
        this.traiterWifi(wireless, pProduit.getLstOptionP().get(PARAM_WIFI), mapOption);
        
        //Traitement des accessoires
        this.traiterAccessoires(request, oProduitCMD);
        
    	
        oProduitCMD.setLstOption(mapOption);
        oProduitCMD.setRef(pProduit.getRef());
        oProduitCMD.setDescription(pProduit.getDescription());
        oProduitCMD.setNom(pProduit.get_nomP());
        oProduitCMD.setCategorie(pProduit.getCategorieP());
        oProduitCMD.setPu(pProduit.getPuP());
        
    	oLigneCommande.setCommande(oCommande);
    	oLigneCommande.setProduitCmd(oProduitCMD);
    	oLigneCommande.setQteCmd(qteProduit);
        
        try {
            if ( this.erreurs.isEmpty() ) {
            	this._oDAOLigneCommande.addLigneCommande(oLigneCommande, pProduit);
                this.resultat = "Succès de l'ajout du produit.";
            }
            else
                this.resultat = "Échec de l'ajout du produit.";
        }
        catch ( DAOException e ) {
        	this.setErreur( "imprévu", "Erreur imprévue lors de la création dans la base de données." );
            this.resultat = "Échec de l'ajout du produit au panier.";
        }

    }

    /**
     * <p>Procédure traiterAccessoires<br />
     * Contrôle la liste des accessoires d'un produit commander</p>
     * @param request : objet HttpServletRequest
     * @param pProduitCMD : objet ProduitCMD
     * */
    private void traiterAccessoires(HttpServletRequest request, ProduitCMD pProduitCMD) {
    	//Recuperation des references des accessoires
        Map<String, Accessoire> mapAccessoires = new HashMap<String, Accessoire>();
    	try {
			mapAccessoires = this._oDAOAccessoire.listerAccessoire();
			
	    	//Enregistrement des accessoires selectionner
	    	Map<String, Accessoire> mapSelect = new HashMap<String, Accessoire>();
	    	for(Accessoire oAccessoire : mapAccessoires.values()){
	    		if(getValeurParametreBoolean(request, oAccessoire.getRef()))
	    			mapSelect.put(oAccessoire.getRef(), oAccessoire);
	    	}
	    	
	        pProduitCMD.setLstAccessoire(mapSelect);
		}
    	catch (DAOException e) {
        	this.setErreur( "imprévu", "Erreur imprévue lors de l'enregistrement des accessoires." );
            this.resultat = "Échec de l'ajout du produit au panier.";
		}
    }
    
    /**
     * <p>Procédure traiterQuantite<br />
     * Contrôle la quantité d'un produit</p>
     * @param pQuantite: la quantite commander
     * @param pLigneCommande: un objet LigneCommande
     * */
    private void traiterQuantite(int pQuantite, LigneCommande pLigneCommande) {
        try {
            this.validationQuantite( pQuantite );
        }
        catch ( Exception e ) {
            this.setErreur( PARAM_QUANTITE, e.getMessage() );
        }
        pLigneCommande.setQteCmd(pQuantite);
    }
    
    /**
     * <p>Procédure traiterCouleur<br />
     * Contrôle la couleur d'un produit commander</p>
     * @param pCouleur: la couleur selectionner
     * @param pOption: objet Option d'une couleur
     * @param pOptions: Map>String, Option> options a enregistrer
     * */
    private void traiterCouleur(String pCouleur, Option pOption , Map<String, Option> pOptions) {
    	if(pCouleur != null && pCouleur.length() != 0 && pCouleur != "Noir"){
    		Option oOption = pOption;
    		int i = 0;
    		String[] tabOption = pOption.getDescription().split("\\|");            
            
    		for(i = 0; i < tabOption.length; i++){
    			if(tabOption[i].equals(pCouleur))
    				break;
    		}
    		oOption.setChoix(i);
    		oOption.setDescription(pCouleur);
    		pOptions.put(pOption.getRef(), oOption);
    	}
    }
    
    /**
     * <p>Procédure traiterCapaciter<br />
     * Contrôle la capacitée d'un produit commander</p>
     * @param pCapacite: la capacite selectionner
     * @param pOption: objet Option d'une couleur
     * @param pOptions: Map>String, Option> options a enregistrer
     * */
    private void traiterCapaciter(String pCapacite, Option pOption , Map<String, Option> pOptions) {
    	if(pCapacite != null && pCapacite.length() != 0 && pCapacite != "16Go"){
    		Option oOption = pOption;
    		int i = 0;
    		String[] tabOption = pOption.getDescription().split("\\|");
    		
    		for(i = 0; i < tabOption.length; i++){
    			if(tabOption[i].equals(pCapacite))
    				break;
    		}
    		oOption.setChoix(i);
    		oOption.setDescription(pCapacite);
    		pOptions.put(pOption.getRef(), oOption);
    	}
    }
    
    /**
     * <p>Procédure traiterWifi<br />
     * Contrôle le Wifi/3G d'un produit commander</p>
     * @param pWifi: vrai si avec Wifi/3G
     * @param pOption: objet Option d'une couleur
     * @param pOptions: Map>String, Option> options a enregistrer
     * */
    private void traiterWifi(boolean pWifi, Option pOption , Map<String, Option> pOptions) {
    	if(pWifi){
    		Option oOption = pOption;
    		oOption.setDescription("Avec 3G");
    		oOption.setChoix(1);
    		pOptions.put(pOption.getRef(), oOption);
    	}
    }
    
    private void validationQuantite(int pQuantite) throws FormValidationException {
        if ( pQuantite < 1 || pQuantite > 10 )
            throw new FormValidationException( "La quantité n'est pas correcte." );
    }
}
